﻿using System;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;
using System.Xml.Xsl;
using Altairis.Nemesis.Gallery.Configuration;

namespace Altairis.Nemesis.Gallery {
    public class InfoPageHandler : IHttpHandler {

        GallerySection config;

        public InfoPageHandler() {
            this.config = GallerySection.GetCurrentOrDefault();
        }

        public bool IsReusable {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context) {
            // Check extension mapping
            string fileName = context.Request.PhysicalPath;
            if (!fileName.EndsWith(".jpg.html", StringComparison.OrdinalIgnoreCase))
                throw new NotSupportedException("ThumbnailHandler can be mapped only to *.jpg.html extension");

            // Ger real file name
            fileName = fileName.Substring(0, fileName.Length - 5);

            // Check if file exists
            if (!System.IO.File.Exists(fileName)) throw new HttpException(404, "Object Not Found");

            // Create XML document with list of files and folders
            XmlDocument listing = CreatePageInfo(fileName);

            string templateFileName = context.Server.MapPath(this.config.Templates.InfoPage);
            if (System.IO.File.Exists(templateFileName)) {
                // XSL template found -- perform transformation
                XslCompiledTransform tran = new XslCompiledTransform();
                tran.Load(templateFileName);
                tran.Transform(listing, new ConfiguredXsltArgumentList(), context.Response.OutputStream);
                context.Response.ContentType = "text/html";
            }
            else {
                // XSL template not found -- send raw XML
                context.Response.ContentType = "text/xml";
                using (XmlWriter w = new XmlTextWriter(context.Response.OutputStream, System.Text.Encoding.UTF8)) {
                    listing.Save(w);
                }
            }

            // Setup caching 
            context.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
            context.Response.Cache.SetExpires(DateTime.Now.AddHours(1));
            context.Response.AddFileDependency(fileName);
            context.Response.AddFileDependency(templateFileName);
            context.Response.Cache.SetLastModifiedFromFileDependencies();
            context.Response.Cache.SetETagFromFileDependencies();
        }

        static XmlDocument CreatePageInfo(string fileName) {
            // Create root element
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(doc.CreateElement("file"));

            // Get file information
            FileInfo fi = new FileInfo(fileName);

            // Check if request is in root folder (some templates may want to format it differently)
            string applicationPath = HttpContext.Current.Request.PhysicalApplicationPath.TrimEnd('\\');
            bool isRoot = applicationPath.Equals(fi.DirectoryName.TrimEnd('\\'), StringComparison.OrdinalIgnoreCase);

            // Get and add file information
            doc.DocumentElement.SetAttribute("title", Path.GetFileNameWithoutExtension(fi.FullName).Replace('_', ' '));
            doc.DocumentElement.SetAttribute("folder", Path.GetFileNameWithoutExtension(fi.DirectoryName).Replace('_', ' '));
            doc.DocumentElement.SetAttribute("isRoot", XmlConvert.ToString(isRoot));
            doc.DocumentElement.AppendChildWithValue("name", fi.Name);
            doc.DocumentElement.AppendChildWithValue("size", fi.Length.ToString());
            doc.DocumentElement.AppendChildWithValue("creationTime", fi.CreationTime.ToString("o"));
            doc.DocumentElement.AppendChildWithValue("lastWriteTime", fi.LastWriteTime.ToString("o"));

                        // Get previous and next files
            string[] fileNames = Directory.GetFiles(fi.DirectoryName, "*.jpg");
            int currentIndex = Array.IndexOf<string>(fileNames, fi.FullName);
            XmlElement position = doc.DocumentElement.AppendChild(doc.CreateElement("position")) as XmlElement;
            position.SetAttribute("current", (currentIndex + 1).ToString());
            position.SetAttribute("max", fileNames.Count().ToString());
            if (currentIndex != 0) doc.DocumentElement.AppendChildWithValue("prevName", Path.GetFileName(fileNames[currentIndex - 1]));
            if (currentIndex != fileNames.Count() - 1) doc.DocumentElement.AppendChildWithValue("nextName", Path.GetFileName(fileNames[currentIndex + 1]));

            // Get picture info
            using (var image = Image.FromFile(fileName)) {
                XmlElement size = doc.DocumentElement.AppendChild(doc.CreateElement("size")) as XmlElement;
                size.SetAttribute("width", image.Width.ToString());
                size.SetAttribute("height", image.Height.ToString());
                size.SetAttribute("bytes", fi.Length.ToString());
            }

            return doc;
        }

    }
}
